﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Data.Common;
using Microsoft.ApplicationBlocks.Data;

namespace Data_Objects.Implementation
{
    /// <summary>
    /// Lớp này quản lý tất cả các phương thức liên quan tới CSDL
    /// </summary>
    /// <remarks>
    /// @author : Hoàng Minh Tuấn
    /// Lớp này xử lý tất các phương thức chi tiết liên quan tới CSDL.
    /// Như Update, Insert, Delete, Get...
    /// Lớp này là 1 lớp tĩnh
    /// </remarks>
    public static class CommandProvider
    {
        //Thuộc tính lấy ra provider : SqlClient, ...
        //Sử dụng lớp DbProviderFactory để truy xuất tới các hệ quản trị CSDL mà không phải sửa đổi lại cấu trúc của lớp này
        private static readonly string dataProvider ="System.Data.SqlClient";// ConfigurationManager.AppSettings.Get("providerName");
        private static readonly DbProviderFactory factory = DbProviderFactories.GetFactory(dataProvider);

        private static readonly string connectionStringName = ConfigurationManager.AppSettings.Get("connectionString");
        private static readonly string connectionString ="Data Source=TUANHM-PC;Initial Catalog=CSEDU;User ID=sa; Password=123456;";// ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;

        #region Handler : String Query

            #region Handler : Update Insert
                /// <summary>
                /// Thực thi lệnh cập nhật trong CSDL 
                /// </summary>
                /// <param name="sqlQuery">Lệnh Sql</param>
                /// <returns>Số lượng dòng trong CSDL sau khi thực thi câu lệnh</returns>
                public static int Update(string sqlQuery)
                {
                    using (DbConnection connection = factory.CreateConnection())
                    {
                        connection.ConnectionString = connectionString;

                        using (DbCommand command = factory.CreateCommand())
                        {
                            command.Connection = connection;
                            command.CommandType = CommandType.Text;
                            command.CommandText = sqlQuery;

                            connection.Open();

                            return command.ExecuteNonQuery();
                        }
                    }
                }
                /// <summary>
                /// Hàm thực thi thao tác thêm mới, và lấy ra ID (Khóa của bảng nếu cần)
                /// </summary>
                /// <param name="sqlQuery">Lệnh Sql</param>
                /// <param name="getID">Nếu cần lấy ra mã sau khi thêm mới thi gán bằng true,ngược lại gán bằng false</param>
                /// <returns>trả về giá trị ID mới sau khi được thêm mới</returns>
                public static int Insert(string sqlQuery, bool getID)
                {
                    int id = -1;
                    using (DbConnection connection = factory.CreateConnection())
                    {
                        connection.ConnectionString = connectionString;
                        using (DbCommand command = factory.CreateCommand())
                        {
                            command.Connection = connection;
                            command.CommandType = CommandType.Text;
                            command.CommandText = sqlQuery;

                            connection.Open();

                            command.ExecuteNonQuery();
                            //Lấy ra ID vừa mới tạo ra
                            if (getID == true)
                            {
                                string idSelect = "";
                                switch (dataProvider)
                                {
                                    //Access
                                    case "System.Data.OleDb":
                                        idSelect = "SELECT @@IDENTITY";
                                        break;
                                    //Sql Server
                                    case "System.Data.SqlClient":
                                        idSelect = "SELECT SCOPE_IDENTITY()";
                                        break;
                                    //Oracle
                                    case "System.Data.OracleClient":
                                        idSelect = "SELECT MySequence.NEXTVAL FROM DUAL";
                                        break;
                                }
                                command.CommandText = idSelect;
                                id = int.Parse(command.ExecuteScalar().ToString());
                            }
                            return id;
                        }
                    }
                }
                /// <summary>
                /// Thực thi câu lệnh thêm mới trong CSDL
                /// </summary>
                /// <param name="sqlQuery">Lệnh Sql</param>
                public static void Insert(string sqlQuery)
                {
                    Insert(sqlQuery, false);
                }
            #endregion

            #region Handler : Data Retrieve
                /// <summary>
                /// Thực thi truy vấn vấn lấy về dữ liệu và đưa vào dataset
                /// </summary>
                /// <param name="sqlQuery">Lệnh sql</param>
                /// <returns>Dữ liệu trả về được đưa vào trong dataset</returns>
                public static DataSet GetDataSet(string sqlQuery)
                {
                    using (DbConnection connection = factory.CreateConnection())
                    {
                        connection.ConnectionString = connectionString;
                        using (DbCommand command = factory.CreateCommand())
                        {
                            command.Connection = connection;
                            command.CommandType = CommandType.Text;
                            command.CommandText = sqlQuery;

                            connection.Open();
                            using (DbDataAdapter apdater = factory.CreateDataAdapter())
                            {
                                apdater.SelectCommand = command;

                                DataSet ds = new DataSet();
                                apdater.Fill(ds);

                                return ds;
                            }
                        }
                    }
                }
                /// <summary>
                /// Thực thi câu lệnh và trả về dữ liệu được đưa vào trong datatable
                /// </summary>
                /// <param name="sqlQuery">Lệnh sql</param>
                /// <returns>Dữ liệu thực thi được trả về trong một datatable</returns>
                public static DataTable GetDataTable(string sqlQuery)
                {
                    using (DbConnection connection = factory.CreateConnection()) 
                    {
                        connection.ConnectionString = connectionString;
                        using (DbCommand command = factory.CreateCommand())
                        {
                            command.Connection = connection;
                            command.CommandType = CommandType.Text;
                            command.CommandText = sqlQuery;

                            connection.Open();
                            using (DbDataAdapter adapter = factory.CreateDataAdapter())
                            {
                                adapter.SelectCommand = command;

                                DataTable dt = new DataTable();
                                adapter.Fill(dt);

                                return dt;
                            }
                        }
                    }
                }
                /// <summary>
                /// Thực thi câu lệnh và trả về dòng dữ liệu đầu tiên
                /// </summary>
                /// <param name="sqlQuery">Lệnh sql</param>
                /// <returns>Trả về dòng dữ liệu</returns>
                public static DataRow GetDataRow(string sqlQuery)
                {
                    DataRow row = null;

                    DataTable dt = GetDataTable(sqlQuery);
                    if (dt.Rows.Count > 0)
                    {
                        row = dt.Rows[0];
                    }
                    return row;
                }
                /// <summary>
                /// Thực thi câu lệnh trả về dữ liệu trong cột đầu tiên ở dòng đầu tiên
                /// </summary>
                /// <param name="sqlQuery">Lệnh sql</param>
                /// <returns>Trả về dữ liệu trong cột đầu tiên ở dòng đầu tiên</returns>
                public static object GetDataScaler(string sqlQuery)
                {
                    using (DbConnection connection = factory.CreateConnection())
                    {
                        connection.ConnectionString = connectionString;
                        using (DbCommand command = factory.CreateCommand())
                        {
                            command.Connection = connection;
                            command.CommandType = CommandType.Text;
                            command.CommandText = sqlQuery;

                            connection.Open();
                            return command.ExecuteScalar();
                        }
                    }
                }
            #endregion

        #endregion

        #region Handler : Stored Procedures

                #region Handler : Update Insert Delete
                /// <summary>
                /// Hàm thực thị thủ tục cập nhật dữ liệu
                /// </summary>
                /// <param name="storeProcedures">Tên thủ tục</param>
                /// <param name="paramater">Tham số</param>
                /// <returns></returns>
                public static int Update(string storeProcedures, DbParameter[] paramater)
                {
                    using (DbConnection connection = factory.CreateConnection())
                    {
                        connection.ConnectionString = connectionString;
                        using (DbCommand command = factory.CreateCommand())
                        {
                            command.Connection = connection;
                            command.CommandType = CommandType.StoredProcedure;
                            command.CommandText = storeProcedures;

                            if (paramater != null)
                            {
                                command.Parameters.AddRange(paramater);
                            }
                            connection.Open();

                            return command.ExecuteNonQuery();
                        }
                    }
                }
                /// <summary>
                /// Hàm thực thi thao tác thêm mới, và lấy ra ID (Khóa của bảng nếu cần)
                /// </summary>
                /// <param name="storeProcedures">Tên thủ tục</param>
                /// <param name="paramater">Tham số</param>
                /// <param name="getID">Nếu cần lấy ra ID sau khi thêm mới gán bằng true,ngược lại gán bằng false</param>
                /// <returns>trả về giá trị ID mới sau khi được thêm mới</returns>
                public static int Insert(string storeProcedures, DbParameter[] paramater, bool getID)
                {
                  //  getID = false;//Lúc nào cũng ko lấy
                    using (DbConnection connection = factory.CreateConnection())
                    {
                        connection.ConnectionString = connectionString;
                        using (DbCommand command = factory.CreateCommand())
                        {
                            command.Connection = connection;
                            command.CommandType = CommandType.StoredProcedure;
                            command.CommandText = storeProcedures;

                            if (paramater != null)
                            {
                                command.Parameters.AddRange(paramater);
                            }
                            connection.Open();
                          command.ExecuteNonQuery();

                            int id = -1;
                            if (getID == true)
                            {
                                string selectID = "";
                                switch (dataProvider)
                                {
                                    //Access
                                    case "System.Data.OleDb":
                                        selectID = "SELECT @@IDENTITY";
                                        break;
                                    //Sql Server
                                    case "System.Data.SqlClient":
                                        selectID = "SELECT @@IDENTITY";//"SCOPE_IDENTITY()";
                                        break;
                                    //Oracle
                                    case "System.Data.OracleClient":
                                        selectID = "SELECT MySequence.NEXTVAL FROM DUAL";
                                        break;
                                }
                                command.CommandType = CommandType.Text;
                                command.CommandText = selectID;
                                string result = command.ExecuteScalar().ToString();
                                if (result=="")
                                {
                                    id = -1; 
                                }
                                else
                                {
                                    id = int.Parse(command.ExecuteScalar().ToString());
                       
                                }
                              }
                            return id;
                        }
                    }
                }
                /// <summary>
                /// Thực thi thao tác thêm mới
                /// </summary>
                /// <param name="storeProcedures">Tên thủ tục</param>
                /// <param name="paramater">Tham số</param>
                public static void Insert(string storeProcedures, DbParameter[] paramater)
                {
                    Insert(storeProcedures, paramater, false);
                }

                /// <summary>
                /// Hàm thực thị thủ tục xóa dữ liệu
                /// </summary>
                /// <param name="storeProcedures">Tên thủ tục</param>
                /// <param name="paramater">Tham số</param>
                /// <returns></returns>
                public static int Delete(string storeProcedures, DbParameter[] paramater)
                {
                    using (DbConnection connection = factory.CreateConnection())
                    {
                        connection.ConnectionString = connectionString;
                        using (DbCommand command = factory.CreateCommand())
                        {
                            command.Connection = connection;
                            command.CommandType = CommandType.StoredProcedure;
                            command.CommandText = storeProcedures;

                            if (paramater != null)
                            {
                                command.Parameters.Add(paramater[0]);
                            }
                            connection.Open();

                            return command.ExecuteNonQuery();
                        }
                    }
                }
            #endregion

            #region Handler : Data Retrieve
                /// <summary>
                /// Thực thi thủ tục vấn lấy về dữ liệu và đưa vào dataset
                /// </summary>
                /// <param name="storedProcedures">Tên thủ tục</param>
                /// <param name="paramater">Tham số</param>
                /// <returns>Dữ liệu trả về được đưa vào trong dataset</returns>
                public static DataSet GetDataset(string storedProcedures, DbParameter[] paramater)
                {
                    using (DbConnection connection = factory.CreateConnection())
                    {
                        connection.ConnectionString = connectionString;
                        using (DbCommand command = factory.CreateCommand())
                        {
                            command.Connection = connection;
                            command.CommandType = CommandType.StoredProcedure;
                            command.CommandText = storedProcedures;

                            if (paramater != null)
                            {
                                command.Parameters.AddRange(paramater);
                            }
                            connection.Open();
                            using (DbDataAdapter adapter = factory.CreateDataAdapter())
                            {
                                adapter.SelectCommand = command;

                                DataSet ds = new DataSet();
                                adapter.Fill(ds);

                                return ds;
                            }
                        }
                    }
                }
                /// <summary>
                /// Thực thi thủ tục và trả về dữ liệu được đưa vào trong datatable
                /// </summary>
                /// <param name="storedProcedures">Tên thủ tục</param>
                /// <param name="paramater">Tham số</param>
                /// <returns>Dữ liệu thực thi được trả về trong một datatable</returns>
                public static DataTable GetDatatable(string storedProcedures,params DbParameter[] paramater)
                {
                    using (DbConnection connection = factory.CreateConnection())
                    {
                        connection.ConnectionString = connectionString;
                        using (DbCommand command = factory.CreateCommand())
                        {
                            command.Connection = connection;
                            command.CommandType = CommandType.StoredProcedure;
                            command.CommandText = storedProcedures;

                            if (paramater != null)
                            {
                                command.Parameters.AddRange(paramater);
                            }
                            connection.Open();
                            using (DbDataAdapter adapter = factory.CreateDataAdapter())
                            {
                                adapter.SelectCommand = command;

                                DataTable dt = new DataTable();
                                adapter.Fill(dt);

                                return dt;
                            }
                        }
                    }
                }
                /// <summary>
                /// Thực thi thủ tục và trả về dòng dữ liệu đầu tiên
                /// </summary>
                /// <param name="storedProcedures">Tên thủ tục</param>
                /// <param name="paramater">Tham số</param>
                /// <returns>Trả về dòng dữ liệu</returns>
                public static DataRow GetDataRow(string storedProcedures, DbParameter[] paramater)
                {
                    DataRow row = null;
                    DataTable dt = GetDatatable(storedProcedures, paramater);
                    if (dt.Rows.Count > 0)
                    {
                        row = dt.Rows[0];
                    }
                    return row;
                }
                /// <summary>
                /// Thực thi thủ tục trả về dữ liệu trong cột đầu tiên ở dòng đầu tiên
                /// </summary>
                /// <param name="storeProcedures">Tên thủ tục</param>
                /// <param name="paramater">tham số</param>
                /// <returns>Trả về dữ liệu trong cột đầu tiên ở dòng đầu tiên</returns>
                public static object GetDataScaler(string storeProcedures, DbParameter[] paramater)
                {
                    using (DbConnection connection = factory.CreateConnection())
                    {
                        connection.ConnectionString = connectionString;
                        using (DbCommand command = factory.CreateCommand())
                        {
                            command.Connection = connection;
                            command.CommandType = CommandType.StoredProcedure;
                            command.CommandText = storeProcedures;

                            if (paramater != null)
                            {
                                command.Parameters.AddRange(paramater);
                            }
                            connection.Open();
                            return command.ExecuteScalar();
                        }
                    }
                }
            #endregion

        #endregion

    }
}